﻿//#####################################################################################################
//int main()
//{
//	setlocale(LC_ALL, "");
//	COORD pos = { 10, 15 };
//
//	wchar_t a = L'庄';
//	wchar_t b = L'梦';
//	wchar_t c = L'涵';
//	wchar_t d = L'我';
//	wchar_t e = L'老';
//	wchar_t f = L'婆';
//	wprintf(L"%lc", a);
//	wprintf(L"%lc", b);
//	wprintf(L"%lc", c);
//	wprintf(L"%lc", d);
//	wprintf(L"%lc", e);
//	wprintf(L"%lc", f);
//	return 0;
//}
//void SetPos(int x, int y)
//{
//	COORD pos = { x,y };
//}
//void WelcomeToGame()
//{
//	SetPos(40, 15);
//	printf("欢迎来到贪吃蛇⼩游戏");
//	SetPos(40, 25);//让按任意键继续的出现的位置好看点
//	system("pause");
//	system("cls");
//	SetPos(25, 12);
//	printf("⽤ ↑ . ↓ . ← . → 分别控制蛇的移动， F3为加速，F4为减速\n");
//	SetPos(25, 13);
//	printf("加速将能得到更⾼的分数。\n");
//	SetPos(40, 25);//让按任意键继续的出现的位置好看点
//	system("pause");
//	system("cls");
//}
//int main()
//{
//	setlocale(LC_ALL, "")
//	//影藏光标操作
//	HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//	CONSOLE_CURSOR_INFO CursorInfo;
//	GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息
//	CursorInfo.bVisible = false; //隐藏控制台光标
//	SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态
//	WelcomeToGame();	
//	return 0;
//}
//mode con 
//title
//COORD
//GetStdHandle -- 获取光标
//#####################################################################################################
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<locale.h>
#include<stdlib.h>
#include<windows.h>
#include<stdbool.h>
#define WCHAR L'口'
#define SNODE L'●'
#define FNODE L'★'
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK) & 0x1) ? 1 : 0 )
typedef enum SnakeDirect
{
	up = 1,
	down,
	lift,
	right
}SnakeDirect;
typedef enum GameState
{
	OK,
	Kill_wall,
	kill_self,
	end_game
}GameState;
typedef struct SnakeNode
{
	int x;
	int y;
	struct SnakeDode* next;
}SnakeNode, * pSnakeNode;
typedef struct Snake
{
	pSnakeNode snake;
	pSnakeNode food;
	SnakeDirect _direct;
	GameState _state;
	int score;
	int foodwight;
	int sleepwight;
}Snake;
void SetPos(short x,short y)
{
	HANDLE houtput = NULL;
	houtput = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos = { x,y };
	SetConsoleCursorPosition(houtput, pos);
}
void SDirect(Snake* p)
{  
	if ((KEY_PRESS(VK_UP) == 1) && (p->_direct != down))
	{
		p->_direct = up;
	}
	else if ((KEY_PRESS(VK_DOWN) == 1) && (p->_direct != up))
	{
		p->_direct = down;
	}
	else if ((KEY_PRESS(VK_LEFT) == 1) && (p->_direct != right))
	{
		p->_direct = lift;
	}
	else if ((KEY_PRESS(VK_RIGHT) == 1) && (p->_direct != lift))
	{
		p->_direct = right;
	}
	else if (KEY_PRESS(VK_SPACE) == 1 )
	{
		SetPos(75, 25);
		system("pause");
	}
	else if (KEY_PRESS(VK_ESCAPE) == 1)
	{
		p->_state = end_game;
		//打印死亡原因;
	}
	else if (KEY_PRESS(VK_F3) == 1)
	{
		if (p->sleepwight < 320)
		{
			p->sleepwight += 20;
			if (p->foodwight > 4)
			p->foodwight -= 2;
		}		
	}
	else if (KEY_PRESS(VK_F4) == 1)
	{
		if (p->sleepwight > 150)
		{
			p->sleepwight -= 10;
			if (p->foodwight < 20)
				p->foodwight += 2;
		}
	}
}
bool JudgeFood(Snake* pp, pSnakeNode food)
{	
	return ((food->x == pp->food->x && food->y == pp->food->y) ? true : false);
}
int main()
{
	setlocale(LC_ALL, "");
	srand((unsigned int)time(NULL));
	//修改控制台大小
	system("mode con cols=100 lines=30");
	//修改名字
	system("title 贪吃的小涵");
	//获取句柄
	HANDLE houtput = NULL;
	houtput = GetStdHandle(STD_OUTPUT_HANDLE);
	//将控制台光标的信息给变量->cursorinfo，类型是：CONSOLE_CURSOR_INFO
	CONSOLE_CURSOR_INFO cursorinfo;
	GetConsoleCursorInfo(houtput, &cursorinfo);
	//隐藏光标
	cursorinfo.bVisible =false;
	//设置光标的大小与可见性
	SetConsoleCursorInfo(houtput, &cursorinfo);
#if 0
	//封装一个SetPos函数->可修改光标的位置;
	SetPos(25, 25);
	//获取按键信息
	GetAsyncKeyState();
#endif 
	//欢迎界面
	SetPos(45, 10);
	printf("欢迎来到贪吃蛇小游戏");
	SetPos(45, 20);
	system("pause");
	SetPos(35, 10);
	printf("玩家可通过.↑.↓.←.→.F4加速.F3减速，来操作：名为小涵的贪吃蛇");
	SetPos(35, 12);
	printf("温馨提示：加速将会得到更高的分数！！！");
	SetPos(45, 20);
	system("pause");
	system("cls");
	//打印地图我要打印一个长为56，宽为28的地图闭合图形
	SetPos(0, 0);
	for (int i = 0; i < 56; i += 2)
	{
		wprintf(L"%lc", WCHAR);
	}
	SetPos(0, 27);
	for (int i = 0; i < 56; i += 2)
	{
		wprintf(L"%lc", WCHAR);
	}
	for(int i = 1; i < 28; i += 1)
	{
		SetPos(0, i);
		wprintf(L"%lc", WCHAR);
	}
	for (int i = 1; i < 28; i += 1)
	{
		SetPos(54, i);
		wprintf(L"%lc", WCHAR);
	}
	//在控制台右边打印信息，以及提示；
	SetPos(75, 8);
	int count = 0;
	printf("本局游戏得分：%d",count);
	SetPos(65, 15);
	printf("玩家可通过.↑.↓.←.→.F3.F4来控制小涵");
	SetPos(65, 16);
	printf(".↑.↓.←.→.用来控制方向");
	SetPos(65, 17);
	printf(".F3用来减速.F4用来加速.");
	SetPos(65, 18);
	printf("若撞到墙体或自身则判定为游戏结束");
	SetPos(65, 19);
	printf("版权归庄梦涵所有");
	SetPos(75, 25);
	system("pause");
	//在封闭空间56*28固定的位置（26，27，28，29，30）*14一个生成庄梦涵();
	Snake p = { 0 };
	for (int i = 0; i < 5; i++)
	{
		pSnakeNode tmp = (pSnakeNode)malloc(sizeof(SnakeNode));
		if (tmp != NULL)
		{	
			tmp->x = 26+i*2;
			tmp->y = 14;
			tmp->next = NULL;
			//然后进行头插入;
			if (p.snake == NULL)
				p.snake = tmp;
			else
			{
				tmp->next = p.snake;
				p.snake = tmp;	
			}
		}
	}
	pSnakeNode cur = p.snake;
	//打印蛇身
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", SNODE);
		cur = cur->next;
	}
	int x, y;
	//产生一个食物
	//判定是否与蛇身重合
again:
	x = rand() % 51 + 2;//2~53
	y = rand() % 26 + 1;//1~26
	cur = p.snake;
	while (cur)
	{
		if (cur->x == x && cur->y == y)
		{
			goto again;
		}
		cur = cur->next;
	}
	SetPos(x, y);
	wprintf(L"%lc",FNODE );
	//初始化
	p.food = (pSnakeNode)malloc(sizeof(SnakeNode));
	p.food->x = x;
	p.food->y = y;
	p._direct = right;
	p._state = OK;
	p.score = 0;
	p.foodwight = 10;
	p.sleepwight = 200;
	//游戏过程
	while (p._state == OK)
	{
		//生成一个结点
		pSnakeNode next = (pSnakeNode)malloc(sizeof(SnakeNode));
		if (next != NULL)
		{
			//指令;
			SDirect(&p);
			//赋值;
			if (p._direct == up)
			{
				next->x = p.snake->x;
				next->y = p.snake->y - 1;
				next->next = NULL;
			}
			else if (p._direct == down)
			{
				next->x = p.snake->x;
				next->y = p.snake->y + 1;
				next->next = NULL;
			}
			else if (p._direct == lift)
			{
				next->x = p.snake->x - 1;
				next->y = p.snake->y;
				next->next = NULL;
			}
			else if (p._direct == right)
			{
				next->x = p.snake->x + 2;
				next->y = p.snake->y;
				next->next = NULL;
			}
			//判定是否是食物
			_Bool ret = JudgeFood(&p, next);
			//进行吃食物操作
			if (ret == true)
			{
				//直接头插即可;
				next->next = p.snake;
				p.snake = next;
			}
			//进行移动操作
			else
			{
				next->next = p.snake;
				p.snake = next;
				pSnakeNode prev = NULL;
				cur = p.snake;
				while (cur->next != NULL)
				{
					prev = cur;
					cur = cur->next;
				}
				prev->next = NULL;
				SetPos(cur->x, cur->y);
				wprintf(L" ");
				cur = NULL;
			}
		}
		cur = p.snake;
		while (cur)
		{
			SetPos(cur->x, cur->y);
			wprintf(L"%lc", SNODE);
			cur = cur->next;
		}
		Sleep(p.sleepwight);
	}
	SetPos(75, 25);
	system("pause");
	return 0;
}
